<template>
  <div class="image-cropper-upload">
    <!-- 多图片上传 -->
    <div v-if="multiple">
      <ul class="img-list">
        <li
          v-for="(detailImg, i) in uploadList"
          :key="getItemKey(detailImg, i)"
          class="item"
        >
          <!-- 媒体展示容器 -->
          <div class="media-container">
            <!-- 图片 -->
            <img
              v-if="detailImg.imgUrl && detailImg.resourceType === 0"
              :src="detailImg.imgUrl"
              class="avatar"
              :style="avatarStyle"
              @mouseenter="handleMouseEnter(i)"
              @mouseleave="handleMouseLeave(i)"
              @error="handleImageError"
              alt="预览图片"
            />
            <!-- 视频 -->
            <video
              v-else-if="detailImg.imgUrl && detailImg.resourceType === 1"
              :src="detailImg.imgUrl"
              class="avatar"
              :style="avatarStyle"
              controls
              @mouseenter="handleMouseEnter(i)"
              @mouseleave="handleMouseLeave(i)"
              @error="handleVideoError"
            >
              您的浏览器不支持视频播放
            </video>
            <!-- 上传占位符 -->
            <div v-else class="avatar-uploader-icon" :style="placeholderStyle">
              <i class="el-icon-plus" />
            </div>

            <!-- 操作按钮 -->
            <div
              v-if="detailImg.imgUrl"
              class="operation-buttons"
              @mouseenter="handleMouseEnter(i)"
              @mouseleave="handleMouseLeave(i)"
            >
              <el-tooltip content="左移" placement="top">
                <i
                  class="el-icon-back operation-icon"
                  @click.stop="handleLeftShift(i)"
                />
              </el-tooltip>

              <el-tooltip content="预览" placement="top">
                <i
                  class="el-icon-zoom-in operation-icon"
                  @click.stop="handlePreviewMultiple(i)"
                />
              </el-tooltip>

              <el-tooltip content="删除" placement="top">
                <i
                  class="el-icon-delete operation-icon"
                  @click.stop="handleRemove(i)"
                />
              </el-tooltip>

              <el-tooltip content="右移" placement="top">
                <i
                  class="el-icon-right operation-icon"
                  @click.stop="handleRightShift(i)"
                />
              </el-tooltip>
            </div>

            <!-- 加载状态 -->
            <div v-if="detailImg.uploading" class="upload-overlay">
              <el-progress
                type="circle"
                :percentage="detailImg.uploadProgress || 0"
                :width="60"
              />
            </div>
          </div>
        </li>

        <!-- 上传按钮 -->
        <li v-if="!isMaxFilesReached">
          <el-upload
            class="avatar-uploader"
            action="#"
            :multiple="meanwhile"
            :auto-upload="false"
            :show-file-list="false"
            :on-change="handleFileChange"
            :before-upload="beforeUpload"
            :accept="acceptTypes"
          >
            <div class="upload-placeholder">
              <i class="el-icon-plus upload-icon" />
              <span class="upload-text">点击上传</span>
              <span class="upload-hint">支持 {{ acceptTypesText }}</span>
            </div>
          </el-upload>
        </li>
      </ul>

      <!-- 文件数量提示 -->
      <div v-if="showFilesCount" class="files-count">
        已上传 {{ uploadList.length }} / {{ maxFiles }} 个文件
      </div>
    </div>

    <!-- 单图片上传 -->
    <div v-else>
      <el-upload
        class="avatar-uploader"
        action="#"
        :auto-upload="false"
        :show-file-list="false"
        :on-change="handleFileChange"
        :before-upload="beforeUpload"
        :http-request="() => {}"
        :accept="acceptTypes"
      >
        <template #default>
          <div class="upload-container">
            <!-- 媒体展示 -->
            <div class="media-container">
              <!-- 图片 -->
              <img
                v-if="imageUrl && fileType === 0 && showPreview"
                :src="imageUrl"
                class="avatar"
                :style="avatarStyle"
                @mouseenter="handleMouseEnterSingle"
                @mouseleave="handleMouseLeaveSingle"
                @error="handleImageError"
                alt="预览图片"
              />
              <!-- 视频 -->
              <video
                v-else-if="imageUrl && fileType === 1"
                :src="imageUrl"
                class="avatar"
                :style="avatarStyle"
                controls
                @mouseenter="handleMouseEnterSingle"
                @mouseleave="handleMouseLeaveSingle"
                @error="handleVideoError"
              >
                您的浏览器不支持视频播放
              </video>
              <!-- 上传占位符 -->
              <div v-else class="upload-placeholder">
                <i class="el-icon-plus upload-icon" />
                <span class="upload-text">点击上传</span>
                <span class="upload-hint">支持 {{ acceptTypesText }}</span>
              </div>

              <!-- 操作按钮 -->
              <div
                v-if="imageUrl"
                class="operation-buttons"
                @mouseenter="handleMouseEnterSingle"
                @mouseleave="handleMouseLeaveSingle"
              >
                <el-tooltip content="预览" placement="top">
                  <i
                    class="el-icon-zoom-in operation-icon"
                    @click.stop="handlePreviewSingle"
                  />
                </el-tooltip>

                <el-tooltip content="重新上传" placement="top">
                  <i
                    class="el-icon-upload operation-icon"
                    @click.stop="handleReupload"
                  />
                </el-tooltip>

                <el-tooltip content="删除" placement="top">
                  <i
                    class="el-icon-delete operation-icon"
                    @click.stop="handleRemoveSingle"
                  />
                </el-tooltip>
              </div>

              <!-- 加载状态 -->
              <div v-if="uploading" class="upload-overlay">
                <el-progress
                  type="circle"
                  :percentage="uploadProgress"
                  :width="60"
                />
              </div>
            </div>
          </div>
        </template>
      </el-upload>
    </div>

    <!-- 裁剪组件弹窗 -->
    <el-dialog
      title="图片裁剪"
      append-to-body
      v-model="cropperModel"
      width="800px"
      :before-close="handleCropperClose"
    >
      <ImageCropper
        ref="vueCropper"
        :img-file="currentFile"
        :fixed="cropFixed"
        :fixed-number="fixedNumber"
        :initial-crop-width="cropInitialWidth"
        :initial-crop-height="cropInitialHeight"
        @upload-files="handleCroppedFile"
        @cropper-error="handleCropperError"
      />
    </el-dialog>

    <!-- 预览弹窗 -->
    <el-dialog
      title="预览"
      append-to-body
      v-model="dialogVisible"
      width="60%"
      center
    >
      <div class="preview-content">
        <img
          v-if="previewFileType === 0"
          :src="dialogImageUrl"
          class="preview-media"
          alt="预览图片"
        />
        <video
          v-else-if="previewFileType === 1"
          :src="dialogImageUrl"
          class="preview-media"
          controls
          autoplay
        >
          您的浏览器不支持视频播放
        </video>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, watch, computed, nextTick } from "vue";
import { ElMessage, ElLoading, ElMessageBox } from "element-plus";
import ImageCropper from "./ImageCropper.vue";

// Props定义
const props = defineProps({
  targetUrl: {
    type: String,
    default: "/api/internal/file/upload2AliYunOSS",
  },
  multiple: {
    type: Boolean,
    default: false,
  },
  initUrl: {
    default: "",
  },
  // 裁剪比例与固定开关
  fixed: {
    type: Boolean,
    default: true,
  },
  fixedNumber: {
    type: Array,
    default: () => [1, 1],
  },
  // 初始裁剪框尺寸（可选）
  initialCropWidth: {
    type: Number,
    default: 0,
  },
  initialCropHeight: {
    type: Number,
    default: 0,
  },
  videoType: {
    type: Boolean,
    default: true,
  },
  meanwhile: {
    type: Boolean,
    default: false,
  },
  width: {
    type: Number,
    default: 150,
  },
  height: {
    type: Number,
    default: 150,
  },
  imgWH: {
    type: Array,
    default: () => [750, 500],
  },
  imgPosition: {
    type: String,
    default: "",
  },
  // 是否显示预览图片
  showPreview: {
    type: Boolean,
    default: true,
  },
  // 新增配置项
  maxFiles: {
    type: Number,
    default: 10,
  },
  maxSize: {
    type: Number,
    default: 5, // MB
  },
  accept: {
    type: String,
    default: "image/*,video/mp4",
  },
});

// Emits定义
const emit = defineEmits([
  "imgupload",
  "upload-success",
  "upload-error",
  "files-change",
]);

// 响应式数据
const currentFile = ref(null);
const fileType = ref(0);
const previewFileType = ref(0);
const imageUrl = ref("");
const dialogImageUrl = ref("");
const uploadList = ref([]);
const dialogVisible = ref(false);
const cropperModel = ref(false);
const uploading = ref(false);
const uploadProgress = ref(0);

// 裁剪配置
const cropFixed = ref(props.fixed);
const cropInitialWidth = ref(props.initialCropWidth || 0);
const cropInitialHeight = ref(props.initialCropHeight || 0);

// 模板引用
const vueCropper = ref(null);

// 计算属性
const avatarStyle = computed(() => ({
  width: `${props.width}px`,
  height: `${props.height}px`,
}));

const placeholderStyle = computed(() => ({
  width: `${props.width}px`,
  height: `${props.height}px`,
  lineHeight: `${props.height}px`,
  fontSize: `${props.height / 6}px`,
}));

const acceptTypes = computed(() => {
  if (props.videoType) {
    return "image/*,video/mp4";
  }
  return "image/*";
});

const acceptTypesText = computed(() => {
  if (props.videoType) {
    return "JPG、PNG格式";
  }
  return "JPG、PNG格式";
});

const isMaxFilesReached = computed(() => {
  return props.multiple && uploadList.value.length >= props.maxFiles;
});

const showFilesCount = computed(() => {
  return props.multiple && props.maxFiles > 1;
});

// 监听props变化
watch(
  () => [props.fixed, props.initialCropWidth, props.initialCropHeight],
  () => {
    cropFixed.value = props.fixed;
    cropInitialWidth.value = props.initialCropWidth || 0;
    cropInitialHeight.value = props.initialCropHeight || 0;
  }
);

// 监听initUrl变化
watch(
  () => props.initUrl,
  (val) => {
    if (val) {
      if (typeof val === "string" || val == null) {
        imageUrl.value = val;
      } else {
        uploadList.value = formatImgArr(val);
      }
    } else {
      imageUrl.value = "";
      uploadList.value = [];
    }
  },
  { immediate: true, deep: true }
);

// 方法定义
// 鼠标操作
const handleMouseEnter = (index) => {
  const elements = document.querySelectorAll(".media-container");
  if (elements[index]) {
    const buttons = elements[index].querySelector(".operation-buttons");
    const avatar = elements[index].querySelector(".avatar");
    if (buttons) buttons.style.display = "flex";
    if (avatar) avatar.style.opacity = "0.7";
  }
};

const handleMouseLeave = (index) => {
  const elements = document.querySelectorAll(".media-container");
  if (elements[index]) {
    const buttons = elements[index].querySelector(".operation-buttons");
    const avatar = elements[index].querySelector(".avatar");
    if (buttons) buttons.style.display = "none";
    if (avatar) avatar.style.opacity = "1";
  }
};

const handleMouseEnterSingle = () => {
  const container = document.querySelector(
    ".upload-container .media-container"
  );
  if (container) {
    const buttons = container.querySelector(".operation-buttons");
    const avatar = container.querySelector(".avatar");
    if (buttons) buttons.style.display = "flex";
    if (avatar) avatar.style.opacity = "0.7";
  }
};

const handleMouseLeaveSingle = () => {
  const container = document.querySelector(
    ".upload-container .media-container"
  );
  if (container) {
    const buttons = container.querySelector(".operation-buttons");
    const avatar = container.querySelector(".avatar");
    if (buttons) buttons.style.display = "none";
    if (avatar) avatar.style.opacity = "1";
  }
};

// 预览操作
const handlePreviewMultiple = (index) => {
  const item = uploadList.value[index];
  if (item && item.imgUrl) {
    dialogImageUrl.value = item.imgUrl;
    previewFileType.value = item.resourceType || 0;
    dialogVisible.value = true;
  }
};

const handlePreviewSingle = () => {
  if (imageUrl.value) {
    dialogImageUrl.value = imageUrl.value;
    previewFileType.value = fileType.value;
    dialogVisible.value = true;
  }
};

// 删除操作
const handleRemove = async (index) => {
  try {
    await ElMessageBox.confirm("确定要删除这个文件吗？", "提示", {
      type: "warning",
      confirmButtonText: "确定",
      cancelButtonText: "取消",
    });

    uploadList.value.splice(index, 1);
    emitFilesChange();
    ElMessage.success("删除成功");
  } catch (error) {
    // 用户取消删除
  }
};

const handleRemoveSingle = async () => {
  try {
    await ElMessageBox.confirm("确定要删除这个文件吗？", "提示", {
      type: "warning",
      confirmButtonText: "确定",
      cancelButtonText: "取消",
    });

    imageUrl.value = "";
    emit("imgupload", null);
    ElMessage.success("删除成功");
  } catch (error) {
    // 用户取消删除
  }
};

// 重新上传
const handleReupload = () => {
  // 触发文件选择
  const uploadInput = document.querySelector(
    ".avatar-uploader .el-upload__input"
  );
  if (uploadInput) {
    uploadInput.click();
  }
};

// 图片排序
const handleLeftShift = (index) => {
  if (index === 0) return;
  const item = uploadList.value[index - 1];
  uploadList.value[index - 1] = uploadList.value[index];
  uploadList.value[index] = item;
  emitFilesChange();
};

const handleRightShift = (index) => {
  if (index === uploadList.value.length - 1) return;
  const item = uploadList.value[index + 1];
  uploadList.value[index + 1] = uploadList.value[index];
  uploadList.value[index] = item;
  emitFilesChange();
};

// 文件上传处理
const handleFileChange = (fileObj, fileList) => {
  console.log("handleFileChange called:", fileObj, props.meanwhile);

  if (isMaxFilesReached.value) {
    ElMessage.warning(`最多只能上传 ${props.maxFiles} 个文件`);
    return;
  }

  currentFile.value = fileObj;

  // 检测文件类型
  if (fileObj.raw.type.startsWith("video/")) {
    fileType.value = 1;
    // 视频直接上传
    handleUploadFile();
  } else if (fileObj.raw.type.startsWith("image/")) {
    fileType.value = 0;
    // 图片需要裁剪
    if (props.meanwhile) {
      console.log("meanwhile is true, uploading directly");
      handleUploadFile();
    } else {
      console.log("meanwhile is false, opening cropper dialog");
      cropperModel.value = true;
      console.log("cropperModel set to:", cropperModel.value);
    }
  } else {
    ElMessage.error("不支持的文件类型");
  }
};

const handleCropConfirm = () => {
  if (vueCropper.value) {
    vueCropper.value.uploadImg("base64");
  }
};

const handleCroppedFile = (data) => {
  handleUploadFile(data);
};

const handleCropperError = (error) => {
  ElMessage.error("图片裁剪失败");
  console.error("Cropper error:", error);
};

const handleCropperClose = (done) => {
  if (vueCropper.value?.isDisabled) {
    done();
  } else {
    ElMessageBox.confirm("裁剪尚未完成，确定要关闭吗？", "提示", {
      type: "warning",
    })
      .then(() => {
        done();
      })
      .catch(() => {
        // 取消关闭
      });
  }
};

const handleUploadFile = async (croppedData = null) => {
  uploading.value = true;
  uploadProgress.value = 0;

  try {
    const formData = new FormData();
    let fileToUpload = currentFile.value.raw;

    // 如果是裁剪后的图片数据
    if (croppedData && fileType.value === 0) {
      const blob = dataURItoBlob(croppedData);
      fileToUpload = new File([blob], currentFile.value.name, {
        type: blob.type,
      });
    }

    formData.append("file", fileToUpload);

    // 模拟上传进度
    const progressInterval = setInterval(() => {
      if (uploadProgress.value < 90) {
        uploadProgress.value += 10;
      }
    }, 200);

    const response = await fetch(props.targetUrl, {
      method: "POST",
      body: formData,
      headers: {
        Authorization: `Bearer ${localStorage.getItem("token") || ""}`,
      },
    });

    clearInterval(progressInterval);
    uploadProgress.value = 100;

    const result = await response.json();

    if (result.code === 0 && result.data) {
      const fileUrl = result.data;

      if (props.multiple) {
        uploadList.value.push({
          imgPosition: props.imgPosition || "",
          imgUrl: fileUrl,
          resourceType: fileType.value,
        });
        emitFilesChange();
      } else {
        imageUrl.value = fileUrl;
        emit("imgupload", fileUrl);
      }

      emit("upload-success", {
        url: fileUrl,
        type: fileType.value,
        file: currentFile.value,
      });

      ElMessage.success("上传成功");
    } else {
      throw new Error(result.message || "上传失败");
    }
  } catch (error) {
    console.error("Upload error:", error);
    ElMessage.error(error.message || "上传失败");
    emit("upload-error", error);
  } finally {
    uploading.value = false;
    uploadProgress.value = 0;
    cropperModel.value = false;

    if (vueCropper.value) {
      vueCropper.value.isDisabled = false;
    }
  }
};

// 工具方法
const formatImgArr = (arr) => {
  if (!arr) return [];
  if (Array.isArray(arr)) {
    return arr.map((item) => {
      if (typeof item === "object" && item !== null) {
        return {
          imgPosition: item.imgPosition || props.imgPosition || "",
          imgUrl: item.imgUrl || item.url || "",
          resourceType: item.resourceType || 0,
        };
      } else {
        return {
          imgPosition: props.imgPosition || "",
          imgUrl: item,
          resourceType: 0,
        };
      }
    });
  }
  return [];
};

const emitFilesChange = () => {
  emit("imgupload", uploadList.value);
  emit("files-change", uploadList.value);
};

const getItemKey = (item, index) => {
  return item.imgUrl ? `${item.imgUrl}-${index}` : `upload-${index}`;
};

const dataURItoBlob = (base64Data) => {
  let byteString;
  if (base64Data.split(",")[0].indexOf("base64") >= 0) {
    byteString = atob(base64Data.split(",")[1]);
  } else {
    byteString = unescape(base64Data.split(",")[1]);
  }
  const mimeString = base64Data.split(",")[0].split(":")[1].split(";")[0];
  const ia = new Uint8Array(byteString.length);
  for (let i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i);
  }
  return new Blob([ia], { type: mimeString });
};

const beforeUpload = (file) => {
  console.log("beforeUpload called:", file, props.maxSize, props.videoType);

  const isImage = file.type.startsWith("image/");
  const isVideo = file.type.startsWith("video/");
  const maxSize = props.maxSize * 1024 * 1024; // 转换为字节

  if (!isImage && !isVideo) {
    console.log("File type not supported:", file.type);
    ElMessage.error("只能上传图片或视频文件");
    return false;
  }

  if (!props.videoType && isVideo) {
    console.log("Video type not allowed");
    ElMessage.error("不支持上传视频文件");
    return false;
  }

  if (file.size > maxSize) {
    console.log("File too large:", file.size, "max:", maxSize);
    ElMessage.error(`文件大小不能超过 ${props.maxSize}MB`);
    return false;
  }

  console.log("beforeUpload passed, returning true");
  return true;
};

const handleImageError = (event) => {
  console.error("图片加载失败:", event);
  ElMessage.warning("图片加载失败");
};

const handleVideoError = (event) => {
  console.error("视频加载失败:", event);
  ElMessage.warning("视频加载失败");
};
</script>

<style lang="scss" scoped>
.image-cropper-upload {
  .avatar-uploader {
    .el-upload {
      border: none;
      border-radius: 6px;
      cursor: pointer;
      position: relative;
      overflow: visible;
    }
  }

  .media-container {
    position: relative;
    border-radius: 6px;
    overflow: hidden;
    transition: all 0.3s ease;

    &:hover {
      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
    }

    .avatar {
      display: block;
      border-radius: 6px;
      object-fit: cover;
      transition: opacity 0.3s ease;
    }

    .avatar-uploader-icon {
      display: flex;
      align-items: center;
      justify-content: center;
      color: #8c939d;
      background-color: #fafafa;
      border: 2px dashed #d9d9d9;
      border-radius: 6px;
      transition: all 0.3s ease;

      &:hover {
        border-color: #409eff;
        color: #409eff;
      }
    }

    .operation-buttons {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      display: none;
      align-items: center;
      justify-content: center;
      gap: 8px;
      background: rgba(0, 0, 0, 0.7);
      border-radius: 20px;
      padding: 8px 12px;
      z-index: 10;
    }

    .operation-icon {
      color: #fff;
      font-size: 18px;
      cursor: pointer;
      transition: color 0.3s ease;

      &:hover {
        color: #409eff;
      }
    }

    .upload-overlay {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(255, 255, 255, 0.9);
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 6px;
      z-index: 5;
    }
  }

  .upload-placeholder {
    width: 100%;
    height: 100%;
    border: 2px dashed #d9d9d9;
    border-radius: 6px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background-color: #fafafa;
    cursor: pointer;
    transition: all 0.3s ease;
    padding: 10px;
    box-sizing: border-box;

    &:hover {
      border-color: #409eff;
      .upload-icon,
      .upload-text {
        color: #409eff;
      }
    }

    .upload-icon {
      font-size: 24px;
      color: #8c939d;
      margin-bottom: 8px;
      transition: color 0.3s ease;
    }

    .upload-text {
      font-size: 14px;
      color: #8c939d;
      margin-bottom: 4px;
      transition: color 0.3s ease;
    }

    .upload-hint {
      font-size: 12px;
      color: #c0c4cc;
      text-align: center;
    }
  }

  .img-list {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin: 0;
    padding: 0;
    list-style: none;

    li.item {
      margin: 0;
    }
  }

  .files-count {
    margin-top: 12px;
    font-size: 12px;
    color: #909399;
    text-align: center;
  }

  .preview-content {
    text-align: center;
    padding: 20px;

    .preview-media {
      max-width: 100%;
      max-height: 70vh;
      border-radius: 6px;
      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
    }
  }
}

// 响应式设计
@media (max-width: 768px) {
  .image-cropper-upload {
    .img-list {
      justify-content: center;
    }

    .operation-buttons {
      padding: 6px 10px;
      gap: 6px;
    }

    .operation-icon {
      font-size: 16px;
    }
  }
}
</style>
